package com.hg.concurent.demo3;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 使用ReentrantLock的condition功能精确唤醒
 * 按顺序:A打印5次,B打印5次,C打印5次
 * created by skh on 2019/12/21
 */
public class ThreadWaitNofifyDemo {
	public static void main(String[] args) {
		ShareResource shareResource = new ShareResource();
		new Thread(() -> {
			for (int i = 0; i < 5; i++) {
			try {
				shareResource.printA();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			}
		}, "A").start();

		new Thread(() -> {
			for (int i = 0; i < 5; i++) {
				try {
					shareResource.printA();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}, "AA").start();

		new Thread(() -> {
			for (int i = 0; i < 5; i++) {
				try {
					shareResource.printA();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}, "AAA").start();

		new Thread(() -> {
			for (int i = 0; i < 5; i++) {
				try {
					shareResource.printB();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}, "B").start();

		new Thread(() -> {
			for (int i = 0; i < 5; i++) {
				try {
					shareResource.printB();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}, "BB").start();

		new Thread(() -> {
			for (int i = 0; i < 5; i++) {
				try {
					shareResource.printB();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}, "BBB").start();

		new Thread(() -> {
			for (int i = 0; i < 5; i++) {
				try {
					shareResource.printC();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}, "C").start();

		new Thread(() -> {
			for (int i = 0; i < 5; i++) {
				try {
					shareResource.printC();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}, "CC").start();
		new Thread(() -> {
			for (int i = 0; i < 5; i++) {
				try {
					shareResource.printC();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}, "CCC").start();
	}

}

class ShareResource {

	private int num = 1; //1:A 2:B 3:C

	private ReentrantLock lock = new ReentrantLock();

	private Condition aCondition = lock.newCondition();
	private Condition bCondition = lock.newCondition();
	private Condition cCondition = lock.newCondition();

	public void printA() throws InterruptedException {
		try {
			lock.lock();
			String name = Thread.currentThread().getName();
			System.out.println(name + "获取锁");
			//判断
			System.out.println("num = " + num);
			while (num != 1) {
				System.out.println(name + "wait");
				aCondition.await();
				System.out.println(name + "被唤醒");

			}

			//干活
			System.out.println(name + "开始干活");

			for (int i = 0; i < 5; i++) {
				System.out.println(name + ":" + i);
			}

			//唤醒
			num = 2;
			bCondition.signalAll();
			System.out.println("开始唤醒B");
		} catch (Exception e) {

		} finally {
			lock.unlock();
		}
	}

	public void printB() throws InterruptedException {
		try {
			lock.lock();
			String name = Thread.currentThread().getName();
			System.out.println(name + "获取锁");
			//判断
			System.out.println("num = " + num);
			while (num != 2) {
				System.out.println(name + "wait");
				bCondition.await();
				System.out.println(name + "被唤醒");

			}

			//干活
			System.out.println(name + "开始干活");

			for (int i = 0; i < 5; i++) {
				System.out.println(name + ":" + i);
			}

			//唤醒
			num = 3;
			cCondition.signalAll();
			System.out.println("开始唤醒C");
		} catch (Exception e) {

		} finally {
			lock.unlock();
		}
	}

	public void printC() throws InterruptedException {
		try {
			lock.lock();
			String name = Thread.currentThread().getName();
			System.out.println(name + "获取锁");
			//判断
			System.out.println("num = " + num);
			while (num != 3) {
				System.out.println(name + "wait");
				cCondition.await();
				System.out.println(name + "被唤醒");

			}

			//干活
			System.out.println(name + "开始干活");

			for (int i = 0; i < 5; i++) {
				System.out.println(name + ":" + i);
			}

			//唤醒
			num = 1;
			aCondition.signalAll();
			System.out.println("开始唤醒A");
		} catch (Exception e) {

		} finally {
			lock.unlock();
		}
	}
}
